package com.derbysoft.lowcostadapter.dswitch2.service.impl;

import com.derbysoft.lowcostadapter.commons.model.Hotel;
import com.derbysoft.lowcostadapter.commons.model.RateCache;
import com.derbysoft.lowcostadapter.commons.redis.service.RateCacheService;
import com.derbysoft.lowcostadapter.commons.redis.service.impl.HSetEntity;
import com.derbysoft.lowcostadapter.commons.redis.utils.DateUtils;
import com.derbysoft.lowcostadapter.commons.redis.utils.KeyValueHelper;
import com.derbysoft.lowcostadapter.commons.utils.DateTimeUtils;
import com.derbysoft.lowcostadapter.dswitch2.service.FlushCacheService;
import com.derbysoft.lowcostadapter.dswitch2.service.helper.GuestCountUtils;
import com.derbysoft.remote.dswitch.core.GenericRQ;
import com.derbysoft.remote.dswitch.core.GenericRS;
import com.derbysoft.remote.dswitch.hotel.dto.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.util.CollectionUtils;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;

/**
 * User: 2012-10-31
 * Date: 12-10-31
 */
@Component("flushCacheService")
public class FlushCacheServiceImpl implements FlushCacheService {
    public static final int ONE_DAY = 24;
    public static final int ONE_THOUSAND = 1000;
    @Autowired
    private RateCacheService rateCacheService;

    @Override
    public void flushCache(GenericRQ<HotelAvailRQ> rq, GenericRS<HotelAvailRS> rs, Hotel hotel) {
        List<GuestCountDTO> guestCounts = rq.getPayload().getAvailCriteria().getRoomStayCandidates().getGuestCounts();
        int adult = GuestCountUtils.getAdults(guestCounts);
        int child = GuestCountUtils.getChildren(guestCounts);
        List<AvailRoomStayDTO> availRoomStayDTOs = rs.getPayload().getHotelAvailRoomStay().getRoomStays();
        if (CollectionUtils.isEmpty(availRoomStayDTOs)) {
            removeRates(hotel.getPropertyID(), adult, child, rq.getPayload().getAvailCriteria().getStayDateRange());
            return;
        }
        saveRates(availRoomStayDTOs, String.valueOf(hotel.getPropertyID()), adult, child);
    }

    @Override
    public void removeRates(GenericRQ<HotelAvailRQ> rq, Hotel hotel) {
        List<GuestCountDTO> guestCounts = rq.getPayload().getAvailCriteria().getRoomStayCandidates().getGuestCounts();
        int adult = GuestCountUtils.getAdults(guestCounts);
        int child = GuestCountUtils.getChildren(guestCounts);
        removeRates(hotel.getPropertyID(), adult, child, rq.getPayload().getAvailCriteria().getStayDateRange());
    }

    private void removeRates(int propertyId, int adult, int child, StayDateRangeDTO stayDateRangeDTO) {
        int los = stayDateRangeDTO.lengthOfStay();
        Date checkIn = stayDateRangeDTO.getCheckInDate();
        for (int i = 0; i < los; i++) {
            String rateKey = RateCache.PREFIX + KeyValueHelper.SEPARATOR + propertyId
                    + KeyValueHelper.SEPARATOR + DateUtils.format(DateUtils.addDays(checkIn, i))
                    + KeyValueHelper.SEPARATOR + adult
                    + KeyValueHelper.SEPARATOR + child;
            rateCacheService.removeAll(rateKey);
        }
    }

    private void saveRates(List<AvailRoomStayDTO> availRoomStayDTOs, String propertyID, int adult, int child) {
        List<HSetEntity> hSetEntities = new ArrayList<HSetEntity>();
        for (AvailRoomStayDTO availRoomStayDTO : availRoomStayDTOs) {
            RateDTO rateDTO = availRoomStayDTO.getRoomRate().getRates().get(0);
            for (int i = 0; i < rateDTO.getDateRange().length(); i++) {
                StringBuilder keyBuilder = new StringBuilder();
                keyBuilder.append(RateCache.PREFIX).append(KeyValueHelper.SEPARATOR);
                keyBuilder.append(propertyID).append(KeyValueHelper.SEPARATOR);
                keyBuilder.append(DateTimeUtils.formatDate(DateTimeUtils.addHours(rateDTO.getDateRange().getStart(), i * ONE_DAY))).append(KeyValueHelper.SEPARATOR);
                keyBuilder.append(adult).append(KeyValueHelper.SEPARATOR);
                keyBuilder.append(child);

                StringBuilder fieldBuilder = new StringBuilder();
                fieldBuilder.append(availRoomStayDTO.getRatePlan().getCode()).append(KeyValueHelper.SEPARATOR);
                fieldBuilder.append(availRoomStayDTO.getRoomType().getCode());

                long expireTime = DateTimeUtils.addHours(rateDTO.getDateRange().getStart(), (i + 2) * ONE_DAY).getTime() / ONE_THOUSAND;
                hSetEntities.add(HSetEntity.build(keyBuilder.toString(), fieldBuilder.toString(), rateDTO.getPureAmount().getAmount().toString(), expireTime));
            }
        }
        rateCacheService.saveHSetEntities(hSetEntities);
    }

    public void setRateCacheService(RateCacheService rateCacheService) {
        this.rateCacheService = rateCacheService;
    }
}
